Ejemplo n.º 1
0
        public void testParsing2()
        {
            ReportTextManager reportTextManager = new ReportTextManager(null, null, obsRepoMock.Object, null, null);
            ObsSession        obsSession        = new ObsSession
            {
                Id         = 5,
                Date       = DateTime.Now,
                ReportText =
                    @"Bla bla bla M11 asdasdd

dsflksd j M12 dsfklfsdfs",
            };
            IDictionary <string, Observation> observationsMap = reportTextManager.Parse(obsSession);

            Assert.AreEqual(2, observationsMap.Count);
        }
Ejemplo n.º 2
0
        public void testParsing3()
        {
            ReportTextManager reportTextManager = new ReportTextManager(null, null, obsRepoMock.Object, null, null);
            ObsSession        obsSession        = new ObsSession
            {
                Id         = 5,
                Date       = DateTime.Now,
                ReportText =
                    @"
I had to look for the planetary nebula NGC 6567, but I failed to locate it. I didn’t even manage to locate the asterism of stars I wanted to use to locate it. I drew a little sketch of the nearby stars to be able to compare with later, but for now nothing. !!

Quickly checked out M18 again, nothing special to say.

M25 which I know has always been a favourite object from Sweden in my 8” reflector *is* pretty cool. Even at low magnification. Faint, but littered with stars.

Having soon done the whole lap around (M24), all I was left with now was NGC 6596, but I just couldn’t get a handle on it. There were two asterisms of stars that could be the object, but I was very uncertain about which one it was.

Just south right between (M24) and (M21) and (M8) was two open cluster close to a few bright stars so I decided to check those out as well before heading back. NGC 6568 was visible but not overly clear. There was a bunch of quite a few medium faint stars.

NGC 6583 I could just not see. !!

Having missed two objects very close to bright stars around the Pipe Nebula, and also not wanting to get two involved in the star fields south of the galactic plane tonight, I headed back to the three stars in a curved line just north of the Pipe Nebula. I tried locating NGC 6325 but felt like I failed to make a definitive observation. I had mistaken the object for a planetary nebula when in fact it is a globular cluster, and I did write down that I thought I saw something faint and large, but I was far from certain. I made a sketch of the star field in order to identify it later, and it did turn out to be correct.

NGC 6369 *was* a planetary nebula though and I found it using the OIII method. Otherwise I think it would have been hard to find. I didn’t see any details, but it was fairly easy to find. Apparently it’s called the Little Ghost Nebula.

Last object in this area, NGC 6401 was super faint. I think I saw it at 35x, and nothing at 17x. If I did see it it must be very faint. Also I seemingly completely missed (B81), (B82) and (B83) which are small dark nebulas just around it. It does look pretty impressive on observatory pictures though with some dark nebulas just . Need to revisit.

Right at the eastern side of the Pipe Nebula is the globular cluster Pal 6 but I failed to locate it with any certainty. Maybe I saw a large diffuse blob. I should spend more time here, I felt I was a bit too fast. On the other hand I read that someone with a 15” scope, though with light pollution and low on the horizon failed to see it. Should revisit.

Now I went south-east of the Pipe Nebula to try to locate the galactic center. I had never been this close to it ever so I had to give it a chance, and just see what’s there. I found Cr 347 and group of stars that I used to try to locate the area but the stars didn’t quite match up with what I was expecting, so I drew a sketch of the area for later investigation. Cr 347 was small and faint by the way. When I came home it turned out I had missed the mark slightly because I had misread the stars on the atlas, not so strange given that they almost didn’t go that deep.

Now crossing the border of the galactic plane, but still just on the galactic north side in the dark side, forming a skewed square with (Cr 347) was three other clusters, Cr 351, NGC 6451, and NGC 6476.

NGC 6425 was most easily found by following a line through an asterism on the east side that looks like an arrow with (NGC 6451) right behind three stars that points right at NGC 6425.

And then if you continue twice further you get to NGC 6416, and then finally M6, which dominates that really dark area of the Milky Way south of the Pipe Nebula. In my notes I’ve said that close to NGC 6416 is like two small clusters separated as in a pie slice kind of way, if not only one is NGC 6416. Not sure what I meant. There are two lines of stars, one in the southern part of the cluster, and one almost outside on the east side. Maybe that’s what I meant. M6 is a big brother, and a very typical open cluster.

Just south-west of (M6) is Tr 28 which kind of stands out with two faint stars and then an almost nebulosity like field of probably fainter stars in the background that can hardly be seen at 25x at least. Could not find any photos of it online, just looks super scattered.

NGC 6374 is completely different in the eyepiece. One pretty bright star and then a bunch of fainter stars that hardly look connected to that brighter star.
",
            };

            IDictionary <string, Observation> observationsMap = reportTextManager.Parse(obsSession);

            Assert.AreEqual(16, observationsMap.Count);
        }
Ejemplo n.º 3
0
        public IActionResult Put(int id, [FromBody] ObsSessionDtoForUpdate obsSessionDtoForUpdate)
        {
            if (obsSessionDtoForUpdate == null)
            {
                return(BadRequest());
            }

            ObsSession obsSessionEntity = _obsSessionsRepository.GetObsSession(id, true, true, true);

            if (obsSessionEntity == null)
            {
                return(NotFound());
            }

            // Lookup and verify the location id
            if (obsSessionDtoForUpdate.LocationId != null)
            {
                Location locationEntity = _locationsRepository.GetLocation(obsSessionDtoForUpdate.LocationId ?? 0);
                if (locationEntity == null)
                {
                    return(NotFound($"Invalid LocationId {obsSessionDtoForUpdate.LocationId}"));
                }
                obsSessionEntity.Location = locationEntity;
            }

            _mapper.Map(obsSessionDtoForUpdate, obsSessionEntity);

            _reportTextManager.ParseAndStoreObservations(obsSessionEntity);

            var result = _obsSessionsRepository.SaveChanges();

            if (!result)
            {
                return(StatusCode(500, "Something went wrong updating the observation session"));
            }

            _logger.LogInformation("Updated an observation session:");
            _logger.LogInformation(PocoPrinter.ToString(obsSessionEntity));

            ObsSession freshObsSessionEntity = _obsSessionsRepository.GetObsSession(id, true, true, true);
            var        resultingDto          = _mapper.Map <ObsSessionDto>(freshObsSessionEntity);

            return(Ok(resultingDto));
        }
Ejemplo n.º 4
0
        public bool DeleteObsSession(ObsSession obsSession)
        {
            // Load all observations
            _dbContext.Entry(obsSession).Collection("Observations").Load();

            foreach (Observation observation in obsSession.Observations)
            {
                // Load each observations' DsoObservations and then remove them
                _dbContext.Entry(observation).Collection("DsoObservations").Load();
                //observation.DsoObservations.RemoveAll(dsoObs => true);  // doesn't seem needed, just loading them
            }

            // Then delete the Observations themselves
            //obsSession.Observations.RemoveAll(obs => true);  // doesn't seem needed, just loading them

            // Finally delete the ObsSession itself
            _dbContext.ObsSessions.Remove(obsSession);
            return(_dbContext.SaveChanges() > 0);
        }
Ejemplo n.º 5
0
        public void testParsing6()
        {
            ReportTextManager reportTextManager = new ReportTextManager(null, null, obsRepoMock.Object, null, null);
            ObsSession        obsSession        = new ObsSession
            {
                Id         = 5,
                Date       = DateTime.Now,
                ReportText =
                    @"This Tr 28 one should match.

NGC 6374 This one should match.

NGC 6374 This one should match
",
            };
            IDictionary <string, Observation> observationsMap = reportTextManager.Parse(obsSession);

            Assert.AreEqual(3, observationsMap.Count);
        }
Ejemplo n.º 6
0
        public IActionResult Delete(int id)
        {
            ObsSession obsSessionEntity = _obsSessionsRepository.GetObsSession(id);

            if (obsSessionEntity == null)
            {
                return(NotFound());
            }


            bool result = _obsSessionsRepository.DeleteObsSession(obsSessionEntity);

            if (!result)
            {
                return(StatusCode(500, "Something went wrong deleting the observation session"));
            }

            _logger.LogInformation("Deleted an observation session:");
            _logger.LogInformation(PocoPrinter.ToString(obsSessionEntity));

            return(Ok());
        }
Ejemplo n.º 7
0
        public void ParseAndStoreObservations(ObsSession obsSession)
        {
            // Parse
            IDictionary <string, Observation> updatedObservations = Parse(obsSession);

            // All returned observations are to be either updated or added, that is decided further down
            // by looking at the currently stored observations.

            // Replace list of Observations on the ObsSession
            _dbContext.Entry(obsSession).Collection("Observations").Load();

            List <Observation> observationsToDelete = obsSession.Observations
                                                      .Where(oldObs => !updatedObservations.ContainsKey(oldObs.Identifier)) // those where there is (not any/no) match in the updatedObservations list
                                                      .ToList();

            // Find out which observations to delete (and not just update)
            foreach (Observation observationToDelete in observationsToDelete)
            {
                // Log them if they have resources on them
                _dbContext.Entry(observationToDelete).Collection("ObsResources").Load();
                if (observationToDelete.ObsResources.Count > 0)
                {
                    _logger.LogInformation("Implicitly (under the hood) deleting an observation containing the following resources:");
                    foreach (ObsResource obsResource in observationToDelete.ObsResources)
                    {
                        _logger.LogInformation(PocoPrinter.ToString(obsResource));
                    }
                }
                // we never delete the ObsResources   // doesn't seem needed, just loading them

                // Load the Observations' DsoObservations and remove them
                _dbContext.Entry(observationToDelete).Collection("DsoObservations").Load();
                //observationToDelete.DsoObservations.RemoveAll(dsoObs => true);  // doesn't seam needed, just loading them

                // Then delete them
                Debug.WriteLine("Deleting observation with identifier " + observationToDelete.Identifier);
                obsSession.Observations.Remove(observationToDelete);
            }

            // First off, start by creating a dictionary of the existing observations for easier lookup
            IDictionary <string, Observation> existingObservations = new Dictionary <string, Observation>();

            foreach (Observation existingObservation in obsSession.Observations)
            {
                existingObservations.Add(existingObservation.Identifier, existingObservation);
            }

            // Then go through observations that already existed, and that should be updated with the new data
            foreach (Observation existingObservation in obsSession.Observations)
            {
                if (updatedObservations.ContainsKey(existingObservation.Identifier))
                {
                    Observation updatedObservation = updatedObservations[existingObservation.Identifier];

                    // Transfer/update the observation
                    existingObservation.Text         = updatedObservation.Text;
                    existingObservation.DisplayOrder = updatedObservation.DisplayOrder;
                    existingObservation.NonDetection = updatedObservation.NonDetection;

                    _dbContext.Entry(existingObservation).Collection("DsoObservations").Load();
                    _dbContext.Entry(existingObservation).Collection("ObsResources").Load();

                    // Set the existing observation id or we get duplicate errors etc when persisting.
                    // During the Parse() stage above we are not aware of the existing observations' ids.
                    foreach (DsoObservation dsoObservation in updatedObservation.DsoObservations)
                    {
                        dsoObservation.ObservationId = existingObservation.Id;
                    }

                    UpdateDsoObservations(existingObservation, updatedObservation);
                    AddNewObsResources(existingObservation, updatedObservation);
                }
            }

            // Finally, add those observations that are new, that didn't exist before
            foreach (Observation updatedObservation in updatedObservations.Values)
            {
                if (!existingObservations.ContainsKey(updatedObservation.Identifier)) // it doesn't exists, add it!
                {
                    var newObservation = updatedObservation;                          // just to clearly indicate that it's a new one
                    // New obs resources will automatically tag along in this situation and get created.
                    Debug.WriteLine("Adding new observation for observation with Identifier " + newObservation.Identifier);
                    obsSession.Observations.Add(newObservation);

                    // Any obs resources get automatically created.
                }
            }

            SaveChanges();
        }
Ejemplo n.º 8
0
        public IDictionary <string, Observation> Parse(ObsSession obsSession)
        {
            string reportText = obsSession.ReportText;
            IDictionary <string, Observation> observationsDict      = new Dictionary <string, Observation>();
            IDictionary <Match, string>       newSectionMatchesDict = new Dictionary <Match, string>();

            // If report text is empty, just return
            if (reportText == null)
            {
                return(observationsDict);
            }

            //string[] primaryCatalogs = { "M", "NGC", "IC", "Sh", "UGC", "PGC" };

            // Get a list of all catalogs designators to search for
            var allCatalogs = _dsoRepo.GetAllCatalogs();

            allCatalogs.Add("Sh2");

            // Regexp for finding DSO names
            string regexpAllCatalogs         = RegExpJoinCatalogs(allCatalogs);
            string introRegexp               = @"(?:\s|\G)"; // non-capturing group of \s or end-of-previous-match (for when the designator starts at the beginning of the line)
            string startingParenthesisRegexp = @"(\()?";
            string endingParenthesisRegexp   = @"(\))?";
            string outroRegexp               = @"[\s\.,]";
            // The ?: at the start of one of the groups is to make that the group is non-capturing.
            // This results in the fourth group always beeing the ending parenthesis.
            string dsoNameRegexp = introRegexp
                                   + startingParenthesisRegexp
                                   + "(" + regexpAllCatalogs + @")[\ |-]?([0-9]+(?:[+-\.]?[0-9]+)*)"
                                   + endingParenthesisRegexp
                                   + outroRegexp;
            var findDsoNamesRegexp = new Regex(dsoNameRegexp, RegexOptions.Compiled | RegexOptions.IgnoreCase);

            // Regexp for finding text sections that include DSO names
            string sectionStart      = @"[^\n]*";                           // the ? after the * makes it non-greedy, or else it doesn't stop at the first section end in singleline (all text as one string) mode
            string sectionEnding     = @".*?(?:\n\n|\r\n\r\n|\n$|\r\n$|$)"; // a section can end with \n\n, or \n$, or just $. The ?: after the parenthesis makes the group non-capturing.
            string findSectionRegexp = sectionStart
                                       + dsoNameRegexp
                                       + sectionEnding;
            // The RegexOptions.Singleline below is what makes it find sections that include a newline and then a Photo:/Link:/Sketch:/Jot: tag.
            // It also makes it necessary to use a ? in .*? to make it non-greedy.
            var findSectionsRegexp = new Regex(findSectionRegexp,
                                               RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);

            string resourceRegexp      = @"(Link|Image|Photo|Sketch|Jot):\s?(.*)";
            var    findResourcesRegexp = new Regex(resourceRegexp, RegexOptions.Compiled | RegexOptions.IgnoreCase);

            string flagOutro = @"(?:\s|\.|$)";  // non-capturing group of \s or . or $

            string nonDetectionRegexp     = @"!!" + flagOutro;
            var    findNonDetectionRegexp = new Regex(nonDetectionRegexp, RegexOptions.Compiled | RegexOptions.IgnoreCase);

            string ratingRegexp     = @"\s(-1|\+1|\+2|\*|\*\*)" + flagOutro;
            var    findRatingRegexp = new Regex(ratingRegexp, RegexOptions.Compiled | RegexOptions.IgnoreCase);

            string followUpRegexp     = @"\s(re-?visit|come back|telescope)" + flagOutro;
            var    findFollowUpRegexp = new Regex(followUpRegexp, RegexOptions.Compiled | RegexOptions.IgnoreCase);

            if (findSectionsRegexp.IsMatch(reportText))  // matches anywhere
            {
                int        obsIndex    = 0;
                ISet <int> foundDsoIds = new HashSet <int>();

                MatchCollection sectionsMatches = findSectionsRegexp.Matches(reportText);  // matching on the whole report text
                foreach (Match sectionsMatch in sectionsMatches)
                {
                    string sectionText = sectionsMatch.Value.Trim();  // the whole section, including resource links

                    string sectionObsText        = GetPartBeforeFirstNewlineIfAny(sectionText);
                    var    dsosInSection         = new Dictionary <int, Dso>();
                    var    obsResourcesInSection = new List <ObsResource>();

                    // Collect all the DSO's in the section text.
                    MatchCollection dsoNameMatches = findDsoNamesRegexp.Matches(sectionObsText);  // matching on a single section
                    foreach (Match dsoNameMatch in dsoNameMatches)
                    {
                        string startingParenthesis = dsoNameMatch.Groups[1].Value;
                        string catalog             = dsoNameMatch.Groups[2].Value;
                        string catalogNo           = dsoNameMatch.Groups[3].Value;
                        string endingParenthesis   = dsoNameMatch.Groups[4].Value;

                        Debug.WriteLine("---------------------------------------------------------");
                        Debug.WriteLine($"Match: {catalog} {catalogNo}");
                        //Debug.WriteLine($"Match: {sectionText}");

                        // Ignore pattern if it's surrounded by parenthesis
                        if (startingParenthesis == "(" || endingParenthesis == ")")
                        {
                            continue;
                        }

                        string dsoName = $"{catalog} {catalogNo}";
                        Dso    dso     = _dsoRepo.GetDsoByName(dsoName, normalize: false);

                        if (dso == null)
                        {
                            Debug.WriteLine("Could not match name");
                            continue;
                        }
                        else
                        {
                            Debug.WriteLine("Found: " + dso.ToString());
                        }

                        if (foundDsoIds.Contains(dso.Id))
                        {
                            throw new ObsToolException("DSO " + dso.ToString() + " found in more than one section of the report text!");
                        }
                        if (dsosInSection.ContainsKey(dso.Id))
                        {
                            continue;  // ignore when the same object is mentioned more than one
                        }

                        dsosInSection.Add(dso.Id, dso);

                        Debug.WriteLine("---------------------------------------------------------");
                    }

                    // Collect all the obs resources
                    MatchCollection resourceMatches = findResourcesRegexp.Matches(sectionText);  // matching on a single section
                    foreach (Match resourceMatch in resourceMatches)
                    {
                        string resourceType = resourceMatch.Groups[1].Value;
                        string resourceUrl  = resourceMatch.Groups[2].Value;
                        Debug.WriteLine($"Match: {resourceType} {resourceUrl}");

                        bool   isGoogleDriveUrl = (resourceType == "Sketch" || resourceType == "Jot");
                        string url = isGoogleDriveUrl ? GetFileIdFromGoogleDriveUrl(resourceUrl) : resourceUrl;

                        var obsResource = new ObsResource
                        {
                            Type = resourceType.Replace("Photo", "Image").ToLower(),
                            Url  = url
                        };
                        obsResourcesInSection.Add(obsResource);
                    }

                    // Collect non-detection
                    bool nonDetection = findNonDetectionRegexp.IsMatch(sectionText);

                    // Collect rating
                    int rating = 0;  // TODO: Change this to nullable and null?
                    if (findRatingRegexp.IsMatch(sectionText))
                    {
                        Match  lastMatch    = findRatingRegexp.Matches(sectionText).Last();
                        string ratingString = lastMatch.Groups[1].Value;
                        if (ratingString == "-1" || ratingString == "+1" || ratingString == "+2")
                        {
                            int.TryParse(ratingString, out rating);
                        }
                        else
                        {
                            rating = ratingString.Length;  // count number of *(stars)
                        }
                    }

                    // Collect follow-up
                    bool followUp = findFollowUpRegexp.IsMatch(sectionText);

                    // If section contained matches regex'ly but that could not be matched against anything
                    // in the DSO database
                    if (dsosInSection.Count == 0)
                    {
                        continue;
                    }

                    // Add any ratings or follow up flags to the DSO's
                    foreach (Dso dso in dsosInSection.Values)
                    {
                        bool noExistingDsoExtra = (dso.DsoExtra == null);
                        if (noExistingDsoExtra)
                        {
                            dso.DsoExtra = new DsoExtra();
                        }
                        // If there is no existing DSO extra, or if this obs session is newer than the obs session used to store
                        // the existing DSO extra, then we replace the attributes in it.
                        if (noExistingDsoExtra || (dso.DsoExtra != null && dso.DsoExtra.ObsSession != null && obsSession.Date >= dso.DsoExtra.ObsSession.Date))
                        {
                            dso.DsoExtra.ObsSession = obsSession;
                            dso.DsoExtra.Rating     = rating;
                            dso.DsoExtra.FollowUp   = followUp;
                        }
                    }

                    string replacedDeprectedIdentifiers = ReplaceDeprecatedObsIdentifiers(sectionText);

                    // Find any existing observations identifier based on the DSO objects the observation contains
                    var observationsIdentifier = FindExistingObsIdentifier(sectionText);
                    if (string.IsNullOrEmpty(observationsIdentifier))
                    {
                        // If none was found in the section text, create one and remember it
                        observationsIdentifier = CreateNewObsIdentifier(obsSession.Id, dsosInSection.Values.ToList());
                        newSectionMatchesDict.Add(sectionsMatch, observationsIdentifier);
                    }

                    // Now, create the observation!
                    Observation observation = new Observation
                    {
                        Text            = sectionObsText,
                        Identifier      = observationsIdentifier,
                        DsoObservations = new List <DsoObservation>(),
                        DisplayOrder    = obsIndex++,
                        NonDetection    = nonDetection
                    };

                    // Add all DSOs to the observation
                    int dsoObsIndex = 0;
                    foreach (Dso dso in dsosInSection.Values)
                    {
                        // Remember all the DSOs in this section for the checks in the next section, and the next etc..
                        foundDsoIds.Add(dso.Id);

                        var dsoObservation = new DsoObservation
                        {
                            Dso          = dso,
                            DsoId        = dso.Id,
                            DisplayOrder = dsoObsIndex++
                                           // no need to add observation.Id since it's just a POCO anyway ??????
                        };

                        // Add the DSOs as DsoObservation's to the observation
                        observation.DsoObservations.Add(dsoObservation);
                    }

                    // Add all obs resources to the observation
                    observation.ObsResources.AddRange(obsResourcesInSection);

                    // Save observation to be returned
                    observationsDict.Add(observation.Identifier, observation);
                }

                // Insert the identifier at the end of all new section matches in the report text.
                // Do it from back to front to keep the match indices from becoming obsolete when you add to the text.
                foreach (var sectionsMatch in sectionsMatches.Cast <Match>().Reverse())
                {
                    if (newSectionMatchesDict.ContainsKey(sectionsMatch))  // only the new ones
                    {
                        // Using the trimmed length to find the end position of the text to be replaced so that the
                        // inserted obs identifier doesn't end up two newlines below, at the start of the next section.
                        int    trimmedLength       = sectionsMatch.Value.Trim().Length;
                        int    sectionEndPos       = sectionsMatch.Index + trimmedLength;
                        string newObsIdentifier    = newSectionMatchesDict[sectionsMatch];
                        string decoratedIdentifier = DecorateObsIdentifier(newObsIdentifier);
                        reportText = reportText.Replace(sectionEndPos, 0, decoratedIdentifier);
                    }
                }

                // Remove all obs resource links.
                // Do it from back to front to keep the match indices from becoming obsolete when you add to the text.
                MatchCollection globalResourceMatches = findResourcesRegexp.Matches(reportText);
                foreach (Match resourceMatch in globalResourceMatches.Cast <Match>().Reverse())
                {
                    reportText = reportText.Replace(resourceMatch.Index, resourceMatch.Length + 1, "");
                }
            }

            obsSession.ReportText = reportText;

            return(observationsDict);
        }