{"action":"created","issue":{"url":"https://api.github.com/repos/inaturalist/inaturalist/issues/630","repository_url":"https://api.github.com/repos/inaturalist/inaturalist","labels_url":"https://api.github.com/repos/inaturalist/inaturalist/issues/630/labels{/name}","comments_url":"https://api.github.com/repos/inaturalist/inaturalist/issues/630/comments","events_url":"https://api.github.com/repos/inaturalist/inaturalist/issues/630/events","html_url":"https://github.com/inaturalist/inaturalist/issues/630","id":94145318,"number":630,"title":"Obs representing globally new taxa","user":{"login":"loarie","id":598026,"avatar_url":"https://avatars.githubusercontent.com/u/598026?v=3","gravatar_id":"","url":"https://api.github.com/users/loarie","html_url":"https://github.com/loarie","followers_url":"https://api.github.com/users/loarie/followers","following_url":"https://api.github.com/users/loarie/following{/other_user}","gists_url":"https://api.github.com/users/loarie/gists{/gist_id}","starred_url":"https://api.github.com/users/loarie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/loarie/subscriptions","organizations_url":"https://api.github.com/users/loarie/orgs","repos_url":"https://api.github.com/users/loarie/repos","events_url":"https://api.github.com/users/loarie/events{/privacy}","received_events_url":"https://api.github.com/users/loarie/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/inaturalist/inaturalist/labels/improvements","name":"improvements","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2015-07-09T20:27:49Z","updated_at":"2016-09-13T00:30:35Z","closed_at":null,"body":"One interesting set of observations are those representing the first of some taxa (and that taxon's descendants) on iNaturalist. \r\n\r\nIt might be nice to be able to search for these 'new taxa'. For example, if I searched for 'new' amphibians I would get only those observations that were the first representation of each taxa (+descendants)\r\n\r\nIt might also be interesting to decorate these observations with a 'new' badge (similar to the invasive and threatened badges currently on obs). Here's the first coastal tailed frog on the site\r\nhttp://www.inaturalist.org/observations/35251\r\n![screen shot 2015-07-09 at 1 26 46 pm](https://cloud.githubusercontent.com/assets/598026/8606093/3b0bdd40-263e-11e5-8b7b-09112c8597a5.png)\r\n\r\nAnd this might be good fodder for our newys stats (e.g. most favs of the week, first of the week etc.)\r\n\r\nPatrick wrote the following code which calculates the set of observations new from some point in the past. But some of the things described above might require that this 'new' state is stored rather than calculated dynamically. Thoughts?\r\n\r\n```ruby\r\ndef observations_with_new_taxon_id(cutoff)\r\n  Observation.where(id: new_obs_ids(cutoff).map{ |r| r[\"id\"] }).\r\n    select(:id, :taxon_id).\r\n    includes({ taxon: :iconic_taxon })\r\nend\r\n\r\ndef new_obs_ids(cutoff)\r\n  Observation.connection.execute(\"\r\n    SELECT DISTINCT new_obs.id\r\n    FROM observations new_obs\r\n    JOIN identifications i ON\r\n      (new_obs.id=i.observation_id and new_obs.taxon_id=i.taxon_id)\r\n    LEFT JOIN observations old_obs ON\r\n      (old_obs.taxon_id = new_obs.taxon_id AND old_obs.id != new_obs.id)\r\n    WHERE new_obs.quality_grade = 'research'\r\n    AND i.created_at > '#{ cutoff }'\r\n    AND old_obs.id IS NULL\")\r\nend\r\n\r\ndef first_right_id(obs, cutoff)\r\n  obs.identifications.where(\"created_at > '#{ cutoff }'\").\r\n    where(taxon_id: obs.taxon_id).first\r\nend\r\n\r\ndef any_descendants_with_obs(obs)\r\n  Observation.connection.execute(\"\r\n    SELECT id FROM observations o\r\n    JOIN taxon_ancestors t ON (o.taxon_id=t.taxon_id)\r\n    WHERE o.id != #{ obs.id }\r\n    AND t.ancestor_taxon_id = #{ obs.taxon_id } LIMIT 1\").first\r\nend\r\n\r\ndef older_ids_of_same_taxon(obs, cutoff)\r\n  Observation.connection.execute(\"\r\n    SELECT id FROM identifications\r\n    WHERE created_at < '#{ cutoff }'\r\n    AND observation_id = #{ obs.id }\r\n    AND taxon_id = #{ obs.taxon_id } LIMIT 1\").first\r\nend\r\n\r\n##############################\r\n\r\ncutoff = 1.month.ago\r\n\r\nobservations_with_new_taxon_id(cutoff).each do |obs|\r\n  if !any_descendants_with_obs(obs) &&\r\n     !older_ids_of_same_taxon(obs, cutoff)\r\n    first_id = first_right_id(obs, cutoff)\r\n    parent = obs.taxon.parent\r\n    puts \"Observation #{ obs.id } is of a new taxon #{ obs.taxon_id } : \" +\r\n         \"#{ obs.taxon.name } (#{ obs.taxon.rank }) \" +\r\n         \"[#{ obs.taxon.iconic_taxon.name }]\"\r\n    puts \"Parent #{ parent.name } has \" +\r\n         \"#{ parent.observations_count } obs \" +\r\n         \"and #{ parent.descendants_count } descendants\"\r\n    puts \"First properly ID'd by #{ first_id.user.login } \" +\r\n         \"on #{ first_id.created_at }\\n\\n\"\r\n  end\r\nend\r\n```"},"comment":{"url":"https://api.github.com/repos/inaturalist/inaturalist/issues/comments/246537804","html_url":"https://github.com/inaturalist/inaturalist/issues/630#issuecomment-246537804","issue_url":"https://api.github.com/repos/inaturalist/inaturalist/issues/630","id":246537804,"user":{"login":"kueda","id":22691,"avatar_url":"https://avatars.githubusercontent.com/u/22691?v=3","gravatar_id":"","url":"https://api.github.com/users/kueda","html_url":"https://github.com/kueda","followers_url":"https://api.github.com/users/kueda/followers","following_url":"https://api.github.com/users/kueda/following{/other_user}","gists_url":"https://api.github.com/users/kueda/gists{/gist_id}","starred_url":"https://api.github.com/users/kueda/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kueda/subscriptions","organizations_url":"https://api.github.com/users/kueda/orgs","repos_url":"https://api.github.com/users/kueda/repos","events_url":"https://api.github.com/users/kueda/events{/privacy}","received_events_url":"https://api.github.com/users/kueda/received_events","type":"User","site_admin":false},"created_at":"2016-09-13T00:30:35Z","updated_at":"2016-09-13T00:30:35Z","body":"I've lost track of what your intent is here. If you are trying to get a \"set of observations [...] representing the first of some taxa (and that taxon's descendants) on iNaturalist,\" why would you have a cutoff? Are you also interested in observations of taxa that have not been observed in 2016 yet or something?"}}
{"actor":{"display_login":"kueda"}}